/*
 * Copyright (c) 2022-2022 All rights Reserved.
 */

package com.driving.core.service.impl;

import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.driving.core.base.BaseServiceImpl;
import com.driving.core.entity.Coach;
import com.driving.core.entity.StudentApply;
import com.driving.core.exception.DrivingException;
import com.driving.core.mapper.ICoachMapper;
import com.driving.core.mapper.IStudentApplyMapper;
import com.driving.core.service.ICoachService;
import com.driving.core.service.dto.CoachDTO;
import com.driving.core.util.Constant;
import com.driving.core.util.Constant.Audience;
import com.driving.core.util.JsonWebToken;
import com.driving.core.util.MessageType.ExceptionType;
import com.driving.core.util.PasswordEncryption;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author SAGITTAR
 * @since 2017
 */
@Slf4j
@AllArgsConstructor
@Service(value = "coachService")
public class CoachServiceImpl extends BaseServiceImpl<ICoachMapper, Coach> implements ICoachService {

    private final IStudentApplyMapper studentApplyMapper;

    @Override
    public boolean passwordUpdateOrReset(CoachDTO dto, String token) {
        int coachId = getCorrespondingIdByTokenOrMobile(baseMapper, token, dto.getMobile(), dto.getOldPassword());
        Coach coach = new Coach(coachId);
        try {
            coach.setPassword(PasswordEncryption.getEncryptedPassword(dto.getPassword()));
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            log.error(e.getLocalizedMessage(), e);
        }
        return updateById(coach);
    }

    /**
     * 查询某个教练的学员
     *
     * @param id 教练ID
     * @return 查询某个教练的学员
     */
    private List<StudentApply> getStudentApplyList(long id) {
        LambdaQueryWrapper<StudentApply> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StudentApply::getCoachId, id);
        return studentApplyMapper.selectList(wrapper);
    }

    @Override
    public List<Map<String, Object>> myStudent(long id) {
        return getStudentApplyList(id).parallelStream().map(apply -> {
            Map<String, Object> currentApply = new HashMap<>(8);
            currentApply.put("name", apply.getName());
            currentApply.put("gender", apply.getGender());
            currentApply.put("email", apply.getEmail());
            currentApply.put("learnType", apply.getLearnType().getLicenseCode());
            return currentApply;
        }).collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> studentDetail(long id, long studentId) {
        List<StudentApply> studentApplyList = getStudentApplyList(id).parallelStream()
                .filter(apply -> apply.getStudentId() == studentId).collect(Collectors.toList());
        if (studentApplyList.isEmpty()) {
            String expMessage = configReader.getExceptionMessage(ExceptionType.STUDENT_NOT_FOUND_WITH_COACH);
            throw new DrivingException(expMessage);
        }
        Map<String, Object> result = new HashMap<>(8);
        StudentApply studentApply = studentApplyList.get(0);
        result.put("name", studentApply.getName());
        result.put("gender", studentApply.getGender());
        result.put("email", studentApply.getEmail());
        result.put("learnType", studentApply.getLearnType().getLicenseCode());
        return result;
    }

    @Override
    public boolean register(CoachDTO coachDTO) {
        if (Objects.nonNull(baseMapper.selectByMobile(coachDTO.getMobile()))) {
            throw new DrivingException(configReader.getExceptionMessage(ExceptionType.USER_EXIST));
        }
        return save(coachDTO.toCoach());
    }

    @Override
    public Map<String, String> login(CoachDTO dto) {
        Coach coach = baseMapper.selectByMobile(dto.getMobile());
        if (Objects.isNull(coach)) {
            throw new DrivingException(configReader.getExceptionMessage(ExceptionType.USER_NOT_FOUND));
        }
        String encryptionPwd = coach.getPassword();
        if (!validatePassword(dto.getPassword(), encryptionPwd)) {
            throw new DrivingException(configReader.getExceptionMessage(ExceptionType.INCORRECT_PASSWORD));
        }
        Map<String, String> loginResult = new HashMap<>(4);
        loginResult.put(Constant.NAME, coach.getName());
        String compact = JsonWebToken.compact(coach.getId(), Audience.COACH, coach.getMobile(), encryptionPwd);
        loginResult.put(Constant.TOKEN, compact);
        return loginResult;
    }
}
